/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import React from 'react';
import { Platform, StyleProp, View, ViewStyle } from 'react-native';
import GestureEventsView, {
  GestureEvent,
} from '../specs/v2/GestureNativeComponent';
import {
  GestureDetector as RNGestureDetector,
  GestureHandlerRootView,
} from 'react-native-gesture-handler';

type Props = {
  gesture: any;
  children: React.ReactNode;
  style?: StyleProp<ViewStyle>;
};

export const GestureWrapper: React.FC<Props> = ({
  gesture,
  children,
  style,
}: Props) => {
  if (Platform.OS === 'harmony') {
    const isMultiGesture =
      gesture && ['simultaneous', 'race', 'exclusive'].includes(gesture.type);
    const multiGestureType = isMultiGesture ? gesture.type : null;
    const multiGestures = isMultiGesture
      ? gesture.gestures.map((g, index) => {
          const config = g.__gestureConfig;
          return [
            config.gestureType, // gestureType
            index, // index (数组中的索引)
            config.minPointers, // minPointers
            config.minDistance, // minDistance
            config.direction, // direction
            config.numberOfTaps, // numberOfTaps
            config.minDurationMs, // minDurationMs
            config.minVelocity, // minVelocity
            config.minAngle, // minAngle
            String(config.repeat), // repeat (转换为字符串)
          ].join(','); // 用逗号拼接
        })
      : [];

    const onStartCallbacks = isMultiGesture
      ? gesture.gestures
          .map((g, index) => ({
            callback: g.__gestureConfig?.onStart || null,
            index: index,
          }))
          .filter(item => item.callback !== null && item.index !== null)
      : [];

    const onUpdateCallbacks = isMultiGesture
      ? gesture.gestures
          .map((g, index) => ({
            callback: g.__gestureConfig?.onUpdate || null,
            index: index,
          }))
          .filter(item => item.callback !== null && item.index !== null)
      : [];

    const onEndCallbacks = isMultiGesture
      ? gesture.gestures
          .map((g, index) => ({
            callback: g.__gestureConfig?.onEnd || null,
            index: index,
          }))
          .filter(item => item.callback !== null && item.index !== null)
      : [];

    const onCancelCallbacks = isMultiGesture
      ? gesture.gestures
          .map((g, index) => ({
            callback: g.__gestureConfig?.onCancel || null,
            index: index,
          }))
          .filter(item => item.callback !== null && item.index !== null)
      : [];

    const onHoverCallbacks = isMultiGesture
      ? gesture.gestures
          .map((g, index) => ({
            callback: g.__gestureConfig?.onHover || null,
            index: index,
          }))
          .filter(item => item.callback !== null && item.index !== null)
      : [];

    const combinedOnStart =
      onStartCallbacks.length > 0
        ? (event: GestureEvent): void => {
            onStartCallbacks.forEach(({ callback, index }) => {
              if (event.type === String(index)) {
                callback(event);
              }
            });
          }
        : undefined;

    const combinedOnUpdate =
      onUpdateCallbacks.length > 0
        ? (event: GestureEvent): void => {
            onUpdateCallbacks.forEach(({ callback, index }) => {
              if (event.type === String(index)) {
                callback(event);
              }
            });
          }
        : undefined;

    const combinedOnEnd =
      onEndCallbacks.length > 0
        ? (event: GestureEvent): void => {
            onEndCallbacks.forEach(({ callback, index }) => {
              if (event.type === String(index)) {
                callback(event);
              }
            });
          }
        : undefined;

    const combinedOnCancel =
      onCancelCallbacks.length > 0
        ? (event: GestureEvent): void => {
            onCancelCallbacks.forEach(({ callback, index }) => {
              if (event.type === String(index)) {
                callback(event);
              }
            });
          }
        : undefined;

    const combinedOnHover =
      onHoverCallbacks.length > 0
        ? (event): void => {
            onHoverCallbacks.forEach(({ callback, index }) => {
              if (event.type === String(index)) {
                callback(event);
              }
            });
          }
        : undefined;

    const cfg = gesture.__gestureConfig || {};
    return (
      <GestureEventsView
        gestureType={cfg.gestureType}
        fingers={cfg.minPointers}
        minDistance={cfg.minDistance}
        direction={cfg.direction}
        numberOfTaps={cfg.numberOfTaps}
        minDurationMs={cfg.minDurationMs}
        minVelocity={cfg.minVelocity}
        minAngle={cfg.minAngle}
        repeat={cfg.repeat}
        onGestureStart={isMultiGesture ? combinedOnStart : cfg.onStart}
        onGestureUpdate={isMultiGesture ? combinedOnUpdate : cfg.onUpdate}
        onGestureEnd={isMultiGesture ? combinedOnEnd : cfg.onEnd}
        onGestureCancel={isMultiGesture ? combinedOnCancel : cfg.onCancel}
        onHover={isMultiGesture ? combinedOnHover : cfg.onHover}
        isMultiGesture={isMultiGesture}
        multiGestureType={multiGestureType}
        multiGestures={multiGestures}
        style={style}
      >
        {children}
      </GestureEventsView>
    );
  } else {
    const resolvedGesture = gesture.gesture || gesture;
    return (
      <GestureHandlerRootView style={{ flex: 1 }}>
        <RNGestureDetector gesture={resolvedGesture}>
          <View style={style}>{children}</View>
        </RNGestureDetector>
      </GestureHandlerRootView>
    );
  }
};
